連續發了 20 幾天的文,能講的也都講了,邁向神乎其技之路只剩下掌握小地方了吧!
之前介紹過 <ng-content> 跟 ContentChild,還有個很類似的是 @ViewChild裝飾器,接著就來看看這是甚麼吧!
這篇建議搭配前一篇一起看。
直接來看範例,這個範例大致跟 @ContentChild 的範例很像,但做了一點修改,晚點我們會做比較。
import {Component} from 'angular2/core';
import {ParentComponent} from './parent';
import {ChildComponent} from './child';
@Component({
selector: 'my-app',
template: `
<h2>App Component</h2>
<my-parent></my-parent>
`,
directives:[ParentComponent,ChildComponent]
})
export class AppComponent {
}
注意到 <my-parent></my-parent> 裡面不用包 <my-child> 了。
import {Component} from 'angular2/core';
@Component({
selector: 'my-child',
template: `
<div>Child Component</div>
`
})
export class ChildComponent {
name:string = 'childName';
}
child 保持不變
import {Component,ViewChild,AfterViewInit} from 'angular2/core';
import {ChildComponent} from './child';
@Component({
selector: 'my-parent',
template: `
<div>Parent Component</div>
<my-child></my-child>
`,
directives:[ChildComponent]
})
export class ParentComponent implements AfterViewInit{
@ViewChild(ChildComponent)
child:ChildComponent;
ngAfterViewInit() {
console.log(this.child)
}
}
改成用 @ViewChild,一樣可以取得 child 的組件內容,不過要在 AfterViewInit 之後才會生效。
如果改成這樣
template: `
<div>Parent Component</div>
<my-child></my-child>
<p>{{child.name}}</p>
`
則會
因為你在他生效前就呼叫了!
可以看到 child 在 parent 中被呼叫了
所以 @ViewChild 跟直接引入組件使用差在哪?
差在如果我們在 parent 的模板沒有使用到 <my-child> 的話,@ViewChild 就會無法調用 child 的組件內容。而如果直接引用 child 組件的話,不使用標籤也沒關係。
@ContentChild 是組件中 selector 標籤閉合之間的子組件,意思就是在 AppComponent 中 <my-parent> 裡面必須要包含 <my-child>,換言之決定權在「使用 <my-parent> 的組件」手上,也就是有 @ContentChild 的上一層。@ViewChild 是組件模板當中的子組件,決定權在當前組件。兩者都有複數形式,@ContentChildren 和 @ViewChildren
什麼時候獲取到子組件的值?
@ContentChild 在父組件生命週期函數 ngAfterContentInit 之後可以獲取到@ViewChild 在父組件生命週期函 ngAfterViewInit 之後可以獲取到